package weiyao.xinxidasai.Utils.Encryption.Chaos;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class CEOLogisticMap {

    private final CEOMap ceoMap;

    public CEOLogisticMap(double r, double x0, Long iterations) {
        this.ceoMap = new CEOMap(r, x0, iterations);
    }

    public List<Byte> generateKeyStream() {
        return ceoMap.generateKeyStream();
    }



    static class CEOMap {
        private double r;         // 控制参数
        private double x0;        // 初始值
        private final Long iterations;   // 迭代次数
        private final int warmupIterations = 1000; // 预热迭代次数

        // 当前状态
        private double x_t;
        private double y_t;
        private double chaosStep;
        private int currentIteration = 0;

        public CEOMap(double r, double x0, Long iterations) {
            // 参数规范化，确保在混沌范围内
            this.r = normalizeR(r);
            this.x0 = normalizeX0(x0);
            this.iterations = iterations;

            // 初始化状态
            double[] warmup = warmUpSystem();
            this.x_t = warmup[0];
            this.y_t = warmup[1];
            this.chaosStep = warmup[2];
        }

        private double normalizeR(double r) {
            // 确保 r 在混沌敏感区域 [3.7, 4.0]
            return 3.7 + (r % 0.3);
        }

        private double normalizeX0(double x0) {
            // 确保 x0 在有效混沌区域 (0.1, 0.9)
            return 0.1 + (x0 % 0.8);
        }

        public List<Byte> generateKeyStream() {
            List<Byte> keyStream = new ArrayList<>();
            double lb = 0.0;
            double ub = 1.0;

            for (int i = 0; i < iterations; i++) {
                // 确定性混沌步长生成
                chaosStep = ceoLogistic(chaosStep, currentIteration);
                double a = 0.1 + 0.8 * chaosStep; // 映射到[0.1,0.9]范围

                // 规范化
                double x_prime = normalize(x_t, lb, ub) - 0.5;
                double y_prime = normalize(y_t, lb, ub) - 0.25;

                // 使用确定性混沌函数
                double x_chaos = r * Math.sin(i * x_prime);
                double y_chaos = y_prime + x_prime;

                // 反规范化
                double x_chaos_prime = denormalize(x_chaos, lb, ub, -0.5, 0.5);
                double y_chaos_prime = denormalize(y_chaos, lb, ub, -0.25, 0.25);

                // 进化方程
                double dx = x_chaos_prime - x_t;
                double dy = y_chaos_prime - y_t;

                double x_t1 = x_t + a * dx;
                double y_t1 = y_t + a * dy;

                x_t = x_t1;
                y_t = y_t1;
                currentIteration++;

                // 生成密钥字节
                byte keyByte = generateKeyByte(x_t, y_t, i);
                keyStream.add(keyByte);
            }
            return keyStream;
        }





        private double[] warmUpSystem() {
            double x_t = x0;
            double y_t = x0; // 使用相关但不同的初始值
            double chaosStep = x0;

            for (int i = 0; i < warmupIterations; i++) {
                chaosStep = ceoLogistic(chaosStep, i);

                // 简单的预热迭代
                double temp = x_t;
                x_t = ceoLogistic(x_t, i);
                y_t = ceoLogistic(y_t, i) + 0.1 * temp;
            }

            return new double[]{x_t, y_t, chaosStep};
        }

        // CEO Logistic Map 核心函数
        private double ceoLogistic(double x, int iteration) {
            // 添加与迭代相关的扰动，保持确定性
            double perturbation = 0.01 * Math.sin(iteration * 0.1);
            return r * x * (1 - x) + perturbation;
        }

        private byte generateKeyByte(double x, double y, int iteration) {
            // 将两个混沌变量组合
            double combined = (x * 2 - 1) + (y * 2 - 1);

            // 映射到 [0, 255] 范围
            int intValue = (int) ((combined + 2) * 63.75); // (0-4) * 63.75 = 0-255
            intValue = intValue & 0xFF; // 确保在字节范围内

            // 应用位重组
            return bitReorganize((byte) intValue, iteration);
        }

        private byte bitReorganize(byte b, int iteration) {
            // 使用简单的位旋转和异或操作
            int value = b & 0xFF;

            // 右旋转 (iteration % 8) 位
            int rotate = iteration % 8;
            value = (value >>> rotate) | (value << (8 - rotate));

            // 应用确定性异或掩码
            int mask = (iteration * 997) & 0xFF; // 大质数
            value = value ^ mask;

            return (byte) (value & 0xFF);
        }

        private double normalize(double val, double lb, double ub) {
            return (val - lb) / (ub - lb);
        }

        private double denormalize(double val, double lb, double ub, double oldMin, double oldMax) {
            double normalized = (val - oldMin) / (oldMax - oldMin);
            return normalized * (ub - lb) + lb;
        }


    }




}